<html>
<!-- ***** BEGIN LICENSE BLOCK *****
   - Version: MPL 1.1/GPL 2.0/LGPL 2.1
   -
   - The contents of this file are subject to the Mozilla Public License Version
   - 1.1 (the "License"); you may not use this file except in compliance with
   - the License. You may obtain a copy of the License at
   - http://www.mozilla.org/MPL/
   -
   - Software distributed under the License is distributed on an "AS IS" basis,
   - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
   - for the specific language governing rights and limitations under the
   - License.
   -
   - The Original Code is PyXPCOM.
   -
   - The Initial Developer of the Original Code is
   - ActiveState Tool Corporation.
   - Portions created by the Initial Developer are Copyright (C) 2000-2001
   - the Initial Developer. All Rights Reserved.
   -
   - Contributor(s):
   -
   - Alternatively, the contents of this file may be used under the terms of
   - either the GNU General Public License Version 2 or later (the "GPL"), or
   - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
   - in which case the provisions of the GPL or the LGPL are applicable instead
   - of those above. If you wish to allow use of your version of this file only
   - under the terms of either the GPL or the LGPL, and not to allow others to
   - use your version of this file under the terms of the MPL, indicate your
   - decision by deleting the provisions above and replace them with the notice
   - and other provisions required by the LGPL or the GPL. If you do not delete
   - the provisions above, a recipient may use your version of this file under
   - the terms of any one of the MPL, the GPL or the LGPL.
   -
   - ***** END LICENSE BLOCK ***** -->

<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
<meta name="ProgId" content="FrontPage.Editor.Document">
<title>Python XPCOM Advanced Topics</title>
</head>

<body>

<h1>Python XPCOM Advanced Topics</h1>

<p>This document contains a series of tidbits that don't fit
anywhere else. As the Python XPCOM Package documentation matures, most of
these topics will have another home.</p>

<h2>XPCOM Services</h2>
<p>An XPCOM service is simply a singleton registered by name.&nbsp; Python has
full support for both using and implementing XPCOM services.&nbsp; To use a
service, use <i>xpcom.components.services</i> just like the JavaScript
counterpart.&nbsp; There is nothing special about implementing a service in
Python; see the standard XPCOM documentation on services for more information.</p>

<h2>nsIVariant</h2>

<p>There is (almost) full support for <i>nsIVariant</i>.&nbsp; Any <i>nsIVariant</i>
parameters will automatically be translated to and from regular Python objects
giving, in effect, a multi-type parameter.&nbsp; This should be automatic, so
there is not much else to say!&nbsp; Note that if you really want, you can
create and pass your own <i>nsIVariant</i> object instead of a regular Python
object, thereby allowing explicit control over the type of variant created.</p>

<h2>nsISupports Primitives.</h2>

<p>There is a set of interfaces described in <i>nsISupportsPrimitives.idl</i>, which I
term collectively the <i>nsISupports Primitives Interfaces</i>.&nbsp; These
are a set of interfaces a component can support to allow automatic conversion to
and from many basic types.&nbsp; For example, an interface can define that it
supports the <i>nsISupportsCString</i> interface, and this could be used by any
program that wishes to get a string representation of the object.&nbsp; If an
interface wishes to expose itself as a &quot;boolean value&quot;, it may choose
to support the <i>nsISupportsPRBool</i> interface.</p>
<p>When you call an XPCOM object (i.e., you have an XPCOM interface you are
calling), you can use
the builtin functions <i>str()</i>, <i>int()</i>, <i>long()</i> etc., on the
object<i>.</i>&nbsp; In the
case of <i>str()</i>, if the object does not support the <i>nsISupportsCString</i>
or <i>nsISupportsString</i> interfaces, the default string <i>str()</i> for the
object will be returned (i.e., what is normally returned for most XPCOM objects -
support for these interface is not very common!).&nbsp; In the case of the numeric functions, a <i>ValueError</i>
exception will be raised if the objects do not support any interface that can be
used for the conversion.&nbsp;<i>ValueError</i> is used instead of <i>TypeError</i>,
as the type itself (i.e., an XPCOM object) can sometimes be used in this context -
hence it is the specific <i>value</i> of the object that is the problem.</p>
<p>The use of <i>repr()</i> on an XPCOM interface object prevents support
attempts for these interfaces, and allows you to see the
&quot;real&quot; object, rather than what the object wants you to see!</p>
<p>When you implement an XPCOM object, you have two choices for implementation
of these interfaces:</p>
<ul>
  <li>You can explicitly handle these interfaces like any other interface.&nbsp;
    In this case, you have full control.&nbsp; However, if you
    implement only one of these standard interfaces, then you are only
    overriding the default behavior for that specific interface - all other
    interfaces not explicitly listed in your class will still get the behavior
    described below.<br>
  </li>
  <li>If your class does not define support for these interfaces, the framework
    will use standard Python class semantics to implement them - i.e., if your
    class provides a <i>__str__</i> method, it will be used to implement <i>nsISupportsCString</i>
    and <i>nsISupportsString</i>, if you provide <i>__int__</i>, <i>__long__</i>,
    <i>__float__</i> etc., methods, they will be used to implement the numeric
    interfaces.&nbsp; If your class defines no such special methods, then the <i>
    QueryInterface()</i> for those interfaces fails (rather than the QI succeeding
    and the operation to fetch the data failing).</li>
</ul>
<blockquote>
<p>This allows for an interesting feature that would not normally be
possible.&nbsp; Consider Python code that does a <i>str()</i> on an&nbsp; XPCOM
interface, and where the XPCOM interface itself is implemented in Python and
provides a <i>__str__</i> method.&nbsp; The <i>str()</i> on the original
interface queries for the <i>nsISupportsCString</i> interface.&nbsp; The
Python implemented object responds to this interface and delegates to the <i>__str__</i>
method. At the end of all this, <i>str()</i> returns the same result
as if the objects were native Python objects with no XPCOM layer in between.</p>

</blockquote>

<h2>Enumerators</h2>

<p>The primary enumerator used by XPCOM is <i>nsISimpleEnumerator</i>.
Although the Python XPCOM package has full support for <i>nsIEnumerator</i>,
since this interface is not &quot;scriptable&quot;, you should avoided using it in interfaces
you design.</p>

<p>When you use <i>nsISimpleEnumerator</i> from Python, the following enhancements
are available:</p>
<ul>
  <li>The <i>GetNext()</i> method takes an optional IID as a parameter. If
    this is specified, the returned object will be of this interface.&nbsp; This
    prevents the manual <i>QueryInterface()</i> generally required from other
    languages.</li>
  <li>There is a <i>FetchBlock(num, [iid])</i> method, which fetches the
    specified number of elements in one operation and returns a Python
    list. This can be useful for large enumerator sets, so the loop
    iterating the elements runs at full C++ speed.</li>
</ul>
<p><i>nsIEnumerator</i> has similar enhancements.</p>
<p>When implementing a Python XPCOM object, the Python class <i>xpcom.server.enumerator.SimpleEnumerator()</i>
can be used.&nbsp; You can pass a standard Python sequence (list, etc), and it
will be correctly wrapped in an <i>nsISimpleEnumerator</i> interface.</p>
<h2>Files</h2>
<p>The Python XPCOM package provides an <i> xpcom.file</i> module.&nbsp; This implements
a Python-like file object on top of the XPCOM/Mozilla stream interfaces.&nbsp;
When run from within the Mozilla environment, this allows you to open almost any
URL supported by Mozilla (including &quot;chrome://&quot; etc.,).</p>
<p>See this module for more information, including test code.</p>
<h2>XPCOM Object Identity</h2>
<p>XPCOM has defined rules for object identity and for how objects must behave
in their <i> QueryInterface()</i> implementations.&nbsp; The Python XPCOM framework
manages this for you; your code can return new Python instances etc., when
responding to new interfaces, and the framework itself will ensure the XPCOM
semantics are followed.&nbsp; Critically, the framework provides no mechanism
for breaking these rules.</p>
<h2>Policies</h2>
<p>The Python XPCOM framework has the concept of &quot;policies&quot; that
define how XPCOM semantics are mapped to Python objects.&nbsp; It is the policy
that implements delegation of <i> QueryInterface()</i>, translates property
references into direct property references, and failing that, &quot;get_name&quot;
and &quot;set_name&quot; calls, decides how to handle exceptions in the
component, and so on.</p>
<p>The default policy is very flexible and suitable for most purposes.
Indeed, the Komodo project has never had to implement a custom policy.
However, you should be aware the feature exists should you wish to do some
bizarre things, such as using Python as a bridge between XPCOM and some other
component technology.</p>

</body>

</html>
